import json
import pandas as pd
from flask import Flask, request, render_template
from sklearn.model_selection import train_test_split        # 数据集划分
from sklearn.preprocessing import OneHotEncoder             # 独热编码
from sklearn.neural_network import MLPClassifier            # 多层感知机分类器
from joblib import dump, load

app = Flask(__name__) 

def train_preserve_model():
    # 加载数据
    data = pd.read_excel('1_传感器数据.xlsx')

    # 去除部分列的空格，发现有部分列有空格，需要去除
    data['传输协议'] = data['传输协议'].str.strip()
    data['测量种类'] = data['测量种类'].str.strip()
    data['测量单位'] = data['测量单位'].str.strip()
    data['需要修改的通信格式'] = data['需要修改的通信格式'].str.strip()

    # 选择特征和目标
    X = data[['传输协议', '测量种类', '最高测量值', '最低测量值', '测量单位', '当前测量值']]
    y = data['需要修改的通信格式']

    # 对分类特征进行独热编码
    encoder = OneHotEncoder()
    X_categorical = encoder.fit_transform(X[['传输协议', '测量种类', '测量单位']])
    X_categorical = pd.DataFrame(X_categorical.toarray(), index=X.index)

    # 保存独热编码器
    dump(encoder, 'encoder.joblib')

    # 合并数值特征和编码后的分类特征
    X_numerical = X[['最高测量值', '最低测量值', '当前测量值']]
    X_prepared = pd.concat([X_categorical, X_numerical], axis=1)

    # 划分训练集和测试集
    X_train, X_test, y_train, _ = train_test_split(X_prepared, y, test_size=0.2, random_state=42)

    # 确保所有特征名称都是字符串类型
    X_train.columns = X_train.columns.astype(str)
    X_test.columns = X_test.columns.astype(str)
    
    # 创建神经网络模型
    model = MLPClassifier(hidden_layer_sizes=(100,), max_iter=300, random_state=1)

    # 训练模型
    model.fit(X_train, y_train)

    # 保存训练模型
    dump(model, 'mlp_model.joblib')

    # 预测测试集
    y_pred = model.predict(X_test)

    # 评估模型
    # accuracy = accuracy_score(y_test, y_pred)
    # print("Accuracy:", accuracy)  


def deep_learn(new_data: list):
    # 加载独热编码器和模型
    encoder = load('encoder.joblib')
    model = load('mlp_model.joblib')
    new_data = pd.DataFrame(new_data)

    # 对新数据的分类特征进行独热编码
    new_categorical = encoder.transform(new_data[['传输协议', '测量种类', '测量单位']])
    new_categorical = pd.DataFrame(new_categorical.toarray(), index=new_data.index)

    # 合并数值特征和编码后的分类特征
    new_numerical = new_data[['最高测量值', '最低测量值', '当前测量值']]
    new_prepared = pd.concat([new_categorical, new_numerical], axis=1)

    new_prepared.columns = new_prepared.columns.astype(str)

    # 使用模型进行预测
    new_predictions = model.predict(new_prepared)
    return new_predictions

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/analysis', methods=['GET'])
def analysis():    
    new_data = {
        '传输协议': [request.args.get('transport-protocol')],
        '测量种类': [request.args.get('measure-type')], 
        '最高测量值': [float(request.args.get('max-measure'))],
        '最低测量值': [float(request.args.get('min-measure'))],
        '测量单位':[request.args.get('measure-unit')],
        '当前测量值': [float(request.args.get('current-measure'))]
    }                   

    if new_data:
        new_predictions = deep_learn(new_data)
        return json.dumps({"code": 200,"prediction": str(new_predictions[0])})
    else:
        return json.dumps({"code": 500, "prediction": ""})

if __name__ == "__main__":
    train_preserve_model()      # 初始化运行  
    app.run(port = 8000, host = "localhost", debug=True) 